package com.learn.enums.annotation;

import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;

import static java.lang.annotation.ElementType.*;

/**
 * 自定义注解@EnumValue
 *
 * @author: MI
 * @email: 448341911@qq.com
 * @createDate: 2023/10/29 17:50
 * @updateUser: MI
 * @updateDate: 2023/10/29 17:50
 * @updateRemark: 修改内容
 * @version: v1.0
 */
@Documented
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {EnumValue.EnumValueValidator.class})
public @interface EnumValue {


    /**
     * 默认错误消息
     */
    String message() default "必须为指定值";

    /**
     * 支持枚举列表验证
     */
    Class<?> value();

    /**
     * 分组
     *
     * @return
     */
    Class<?>[] groups() default {};

    /**
     * 负载
     *
     * @return
     */
    Class<? extends Payload>[] payload() default {};

    /**
     * 指定多个时使用
     */
    @Documented
    @Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @interface list {
        EnumValue[] value();
    }

    /**
     * 校验类逻辑定义
     */
    class EnumValueValidator implements ConstraintValidator<EnumValue, String> {

        /**
         * 枚举类
         */
        private Class<?> enumValue;

        /**
         * 初始化方法
         *
         * @param constraintAnnotation
         */
        @Override
        public void initialize(EnumValue constraintAnnotation) {
            enumValue = constraintAnnotation.value();
        }

        /**
         * 校验方法
         *
         * @param value
         * @param context
         * @return
         */
        @SneakyThrows
        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
            if (StrUtil.isBlank(value)) {
                return Boolean.TRUE;
            }
            // 针对枚举类型的校验匹配
            if (enumValue != null && enumValue.isEnum()) {
                // 枚举类验证
                Object[] objs = enumValue.getEnumConstants();
                // 这里需要注意，定义枚举时，枚举值名称统一用value表示
                Method method = enumValue.getMethod("getCode");
                for (Object obj : objs) {
                    Object code = method.invoke(obj, null);
                    if (value.equals(code.toString())) {
                        return Boolean.TRUE;
                    }
                }
            }
            return Boolean.FALSE;
        }
    }
}
